#include "resource_monitor.h"
#include <QFile>
#include <QTextStream>
#include <QRegularExpression>
#include <QProcess>
#include <QStandardPaths>
#include <QDir>
#include <QDateTime>
#include <QDebug>
#include <fstream>
#include <sstream>

ResourceMonitor::ResourceMonitor(QObject *parent)
    : QObject(parent)
    , m_cpuUsage(0.0)
    , m_memoryUsage(0.0)
    , m_swapUsage(0.0)
    , m_cpuFrequency(0)
    , m_cpuMaxTemperature(0)
    , m_avgTemperature(0)
    , m_hddTemperature(0)
    , m_otherHardwareTemperature(0)
{
}

double ResourceMonitor::cpuUsage() const
{
    return m_cpuUsage;
}

double ResourceMonitor::memoryUsage() const
{
    return m_memoryUsage;
}

double ResourceMonitor::swapUsage() const
{
    return m_swapUsage;
}

int ResourceMonitor::cpuFrequency() const
{
    return m_cpuFrequency;
}

int ResourceMonitor::cpuMaxTemperature() const
{
    return m_cpuMaxTemperature;
}

int ResourceMonitor::avgTemperature() const
{
    return m_avgTemperature;
}

int ResourceMonitor::hddTemperature() const
{
    return m_hddTemperature;
}

int ResourceMonitor::otherHardwareTemperature() const
{
    return m_otherHardwareTemperature;
}

void ResourceMonitor::update()
{
    // 更新所有监控数据
    updateCpuUsage();
    updateMemoryUsage();
    updateSwapUsage();
    updateCpuFrequency();
    updateTemperatures();
    
    // 发出信号通知数据已更新
    emit dataUpdated();
}

void ResourceMonitor::updateCpuUsage()
{
    static unsigned long long lastTotal = 0;
    static unsigned long long lastIdle = 0;
    
    std::ifstream file("/proc/stat");
    std::string line;
    
    if (std::getline(file, line)) {
        std::istringstream ss(line);
        std::string cpuLabel;
        unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
        
        ss >> cpuLabel >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal;
        
        unsigned long long currentIdle = idle + iowait;
        unsigned long long currentTotal = user + nice + system + idle + iowait + irq + softirq + steal;
        
        if (lastTotal != 0) {
            unsigned long long totalDiff = currentTotal - lastTotal;
            unsigned long long idleDiff = currentIdle - lastIdle;
            
            m_cpuUsage = 100.0 * (totalDiff - idleDiff) / totalDiff;
        }
        
        lastTotal = currentTotal;
        lastIdle = currentIdle;
    }
}

void ResourceMonitor::updateMemoryUsage()
{
    std::ifstream file("/proc/meminfo");
    std::string line;
    long long memTotal = 0;
    long long memAvailable = 0;
    
    while (std::getline(file, line)) {
        if (line.substr(0, 8) == "MemTotal") {
            std::istringstream ss(line);
            std::string label;
            ss >> label >> memTotal;
        } else if (line.substr(0, 12) == "MemAvailable") {
            std::istringstream ss(line);
            std::string label;
            ss >> label >> memAvailable;
            break;
        }
    }
    
    if (memTotal > 0) {
        m_memoryUsage = 100.0 * (memTotal - memAvailable) / memTotal;
    }
}

void ResourceMonitor::updateSwapUsage()
{
    std::ifstream file("/proc/meminfo");
    std::string line;
    long long swapTotal = 0;
    long long swapFree = 0;
    
    while (std::getline(file, line)) {
        if (line.find("SwapTotal:") != std::string::npos) {
            std::istringstream ss(line);
            std::string label;
            ss >> label >> swapTotal;
        } else if (line.find("SwapFree:") != std::string::npos) {
            std::istringstream ss(line);
            std::string label;
            ss >> label >> swapFree;
            break;
        }
    }
    
    if (swapTotal > 0) {
        m_swapUsage = 100.0 * (swapTotal - swapFree) / swapTotal;
    }
}

void ResourceMonitor::updateCpuFrequency()
{
    // 读取CPU频率信息
    QFile file("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
    if (file.open(QIODevice::ReadOnly)) {
        QString content = file.readAll().trimmed();
        file.close();
        
        bool ok;
        int currentFreq = content.toInt(&ok);
        if (ok) {
            m_cpuFrequency = currentFreq / 1000; // 转换为MHz
        }
    }
}

void ResourceMonitor::updateTemperatures()
{
    // CPU 最高温度
    std::ifstream cpuTempFile("/sys/class/thermal/thermal_zone0/temp");
    if (cpuTempFile.is_open()) {
        long long temp;
        cpuTempFile >> temp;
        m_cpuMaxTemperature = temp / 1000; // 单位为摄氏度
        cpuTempFile.close();
    }

    // 平均温度（假设 thermal_zone1 是平均温度）
    std::ifstream avgTempFile("/sys/class/thermal/thermal_zone1/temp");
    if (avgTempFile.is_open()) {
        long long temp;
        avgTempFile >> temp;
        m_avgTemperature = temp / 1000;
        avgTempFile.close();
    }

    // 硬盘温度（通过 hddtemp 或 smartctl 获取，这里简化为模拟）
    // 假设使用 smartctl 命令获取 HDD 温度
    QProcess process;
    process.start("smartctl", QStringList() << "-A" << "/dev/sda");
    process.waitForFinished();
    QString output = process.readAllStandardOutput();
    QRegularExpression re("Temperature_Celsius: ([0-9]+)");
    QRegularExpressionMatch match = re.match(output);
    if (match.hasMatch()) {
        m_hddTemperature = match.captured(1).toInt();
    }

    // 其他硬件温度（可扩展）
    m_otherHardwareTemperature = m_cpuMaxTemperature; // 暂时与 CPU 最高温度一致
}

int ResourceMonitor::getCPUMaxTemperature()
{
    int maxTemp = 0;
    bool found = false;
    
    // 遍历所有thermal_zone目录
    for (int i = 0; i < 10; i++) {
        QString tempPath = QString("/sys/class/thermal/thermal_zone%1/temp").arg(i);
        std::ifstream file(tempPath.toStdString());
        if (file.is_open()) {
            std::string line;
            if (std::getline(file, line)) {
                try {
                    int temp = std::stoi(line) / 1000; // 转换为摄氏度
                    if (!found || temp > maxTemp) {
                        maxTemp = temp;
                        found = true;
                    }
                } catch (...) {
                    continue;
                }
            }
        }
    }
    
    // 同时检查hwmon目录
    for (int i = 0; i < 10; i++) {
        QString tempPath = QString("/sys/class/hwmon/hwmon%1/temp1_input").arg(i);
        std::ifstream file(tempPath.toStdString());
        if (file.is_open()) {
            std::string line;
            if (std::getline(file, line)) {
                try {
                    int temp = std::stoi(line) / 1000; // 转换为摄氏度
                    if (!found || temp > maxTemp) {
                        maxTemp = temp;
                        found = true;
                    }
                } catch (...) {
                    continue;
                }
            }
        }
    }
    
    return found ? maxTemp : 0;
}

int ResourceMonitor::getAverageTemperature()
{
    int totalTemp = 0;
    int count = 0;
    
    // 遍历所有thermal_zone目录
    for (int i = 0; i < 10; i++) {
        QString tempPath = QString("/sys/class/thermal/thermal_zone%1/temp").arg(i);
        std::ifstream file(tempPath.toStdString());
        if (file.is_open()) {
            std::string line;
            if (std::getline(file, line)) {
                try {
                    int temp = std::stoi(line) / 1000; // 转换为摄氏度
                    totalTemp += temp;
                    count++;
                } catch (...) {
                    continue;
                }
            }
        }
    }
    
    // 同时检查hwmon目录
    for (int i = 0; i < 10; i++) {
        QString tempPath = QString("/sys/class/hwmon/hwmon%1/temp1_input").arg(i);
        std::ifstream file(tempPath.toStdString());
        if (file.is_open()) {
            std::string line;
            if (std::getline(file, line)) {
                try {
                    int temp = std::stoi(line) / 1000; // 转换为摄氏度
                    totalTemp += temp;
                    count++;
                } catch (...) {
                    continue;
                }
            }
        }
    }
    
    if (count > 0) {
        return totalTemp / count;
    }
    
    return 0;
}

int ResourceMonitor::getHDDTemperature()
{
    // 首先尝试使用smartctl命令获取硬盘温度
    QProcess process;
    process.start("smartctl", QStringList() << "-A" << "/dev/sda");
    process.waitForFinished(3000); // 等待最多3秒
    
    if (process.exitCode() == 0) {
        QString output = process.readAllStandardOutput();
        QStringList lines = output.split('\n');
        
        // 查找温度行
        for (const QString &line : lines) {
            if (line.contains("Temperature_Celsius", Qt::CaseInsensitive) || 
                line.contains("Airflow_Temperature_Cel", Qt::CaseInsensitive)) {
                QStringList parts = line.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
                if (parts.size() >= 10) {
                    bool ok;
                    int temp = parts[9].toInt(&ok);
                    if (ok) {
                        return temp;
                    }
                }
            }
        }
    }
    
    // 如果smartctl不可用或失败，尝试从系统文件读取
    const char* hddTempFiles[] = {
        "/sys/class/hwmon/hwmon0/temp1_input",
        "/sys/class/hwmon/hwmon1/temp1_input",
        "/sys/class/hwmon/hwmon2/temp1_input",
        "/sys/class/hwmon/hwmon3/temp1_input"
    };
    
    for (const char* tempFile : hddTempFiles) {
        std::ifstream file(tempFile);
        if (file.is_open()) {
            std::string line;
            if (std::getline(file, line)) {
                try {
                    int temp = std::stoi(line) / 1000; // 转换为摄氏度
                    // 硬盘温度通常比CPU温度低，如果读取的温度在合理范围内，则认为是硬盘温度
                    if (temp > 0 && temp < 100) {
                        return temp;
                    }
                } catch (...) {
                    continue;
                }
            }
        }
    }
    
    // 回退到默认值
    return 0;
}

int ResourceMonitor::getOtherHardwareTemperature()
{
    // 尝试从多个可能的温度文件中读取
    const char* tempFiles[] = {
        "/sys/class/thermal/thermal_zone0/temp",
        "/sys/class/hwmon/hwmon0/temp1_input",
        "/sys/class/hwmon/hwmon1/temp1_input",
        "/sys/class/hwmon/hwmon2/temp1_input"
    };
    
    for (const char* tempFile : tempFiles) {
        std::ifstream file(tempFile);
        if (file.is_open()) {
            std::string line;
            if (std::getline(file, line)) {
                try {
                    int temp = std::stoi(line) / 1000; // 转换为摄氏度
                    return temp;
                } catch (...) {
                    continue;
                }
            }
        }
    }
    
    return 0;
}